﻿using System;
using UnityEngine;

namespace RootMotion
{
	// Token: 0x020000EF RID: 239
	[Serializable]
	public class BipedReferences
	{
		// Token: 0x1700009D RID: 157
		// (get) Token: 0x060006BB RID: 1723 RVA: 0x0003BF84 File Offset: 0x0003A184
		public bool isFilled
		{
			get
			{
				if (this.root == null)
				{
					return false;
				}
				if (this.pelvis == null)
				{
					return false;
				}
				if (this.leftThigh == null || this.leftCalf == null || this.leftFoot == null)
				{
					return false;
				}
				if (this.rightThigh == null || this.rightCalf == null || this.rightFoot == null)
				{
					return false;
				}
				if (this.leftUpperArm == null || this.leftForearm == null || this.leftHand == null)
				{
					return false;
				}
				if (this.rightUpperArm == null || this.rightForearm == null || this.rightHand == null)
				{
					return false;
				}
				foreach (Transform x in this.spine)
				{
					if (x == null)
					{
						return false;
					}
				}
				foreach (Transform x2 in this.eyes)
				{
					if (x2 == null)
					{
						return false;
					}
				}
				return true;
			}
		}

		// Token: 0x1700009E RID: 158
		// (get) Token: 0x060006BC RID: 1724 RVA: 0x00006618 File Offset: 0x00004818
		public bool isEmpty
		{
			get
			{
				return this.IsEmpty(true);
			}
		}

		// Token: 0x060006BD RID: 1725 RVA: 0x0003C0F0 File Offset: 0x0003A2F0
		public bool IsEmpty(bool includeRoot)
		{
			if (includeRoot && this.root != null)
			{
				return false;
			}
			if (this.pelvis != null || this.head != null)
			{
				return false;
			}
			if (this.leftThigh != null || this.leftCalf != null || this.leftFoot != null)
			{
				return false;
			}
			if (this.rightThigh != null || this.rightCalf != null || this.rightFoot != null)
			{
				return false;
			}
			if (this.leftUpperArm != null || this.leftForearm != null || this.leftHand != null)
			{
				return false;
			}
			if (this.rightUpperArm != null || this.rightForearm != null || this.rightHand != null)
			{
				return false;
			}
			foreach (Transform x in this.spine)
			{
				if (x != null)
				{
					return false;
				}
			}
			foreach (Transform x2 in this.eyes)
			{
				if (x2 != null)
				{
					return false;
				}
			}
			return true;
		}

		// Token: 0x060006BE RID: 1726 RVA: 0x0003C274 File Offset: 0x0003A474
		public static bool AutoDetectReferences(ref BipedReferences references, Transform root, BipedReferences.AutoDetectParams autoDetectParams)
		{
			if (references == null)
			{
				references = new BipedReferences();
			}
			references.root = root;
			Animator component = root.GetComponent<Animator>();
			if (component != null && component.isHuman)
			{
				BipedReferences.AssignHumanoidReferences(ref references, component, autoDetectParams);
				return true;
			}
			BipedReferences.DetectReferencesByNaming(ref references, root, autoDetectParams);
			Warning.logged = false;
			if (!references.isFilled)
			{
				Warning.Log("BipedReferences contains one or more missing Transforms.", root, true);
				return false;
			}
			string empty = string.Empty;
			if (BipedReferences.SetupError(references, ref empty))
			{
				Warning.Log(empty, references.root, true);
				return false;
			}
			if (BipedReferences.SetupWarning(references, ref empty))
			{
				Warning.Log(empty, references.root, true);
			}
			return true;
		}

		// Token: 0x060006BF RID: 1727 RVA: 0x0003C328 File Offset: 0x0003A528
		public static void DetectReferencesByNaming(ref BipedReferences references, Transform root, BipedReferences.AutoDetectParams autoDetectParams)
		{
			if (references == null)
			{
				references = new BipedReferences();
			}
			Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>();
			BipedReferences.DetectLimb(BipedNaming.BoneType.Arm, BipedNaming.BoneSide.Left, ref references.leftUpperArm, ref references.leftForearm, ref references.leftHand, componentsInChildren);
			BipedReferences.DetectLimb(BipedNaming.BoneType.Arm, BipedNaming.BoneSide.Right, ref references.rightUpperArm, ref references.rightForearm, ref references.rightHand, componentsInChildren);
			BipedReferences.DetectLimb(BipedNaming.BoneType.Leg, BipedNaming.BoneSide.Left, ref references.leftThigh, ref references.leftCalf, ref references.leftFoot, componentsInChildren);
			BipedReferences.DetectLimb(BipedNaming.BoneType.Leg, BipedNaming.BoneSide.Right, ref references.rightThigh, ref references.rightCalf, ref references.rightFoot, componentsInChildren);
			references.head = BipedNaming.GetBone(componentsInChildren, BipedNaming.BoneType.Head, BipedNaming.BoneSide.Center, new string[0][]);
			references.pelvis = BipedNaming.GetNamingMatch(componentsInChildren, new string[][]
			{
				BipedNaming.pelvis
			});
			if ((references.pelvis == null || !Hierarchy.IsAncestor(references.leftThigh, references.pelvis)) && references.leftThigh != null)
			{
				references.pelvis = references.leftThigh.parent;
			}
			if (references.leftUpperArm != null && references.rightUpperArm != null && references.pelvis != null && references.leftThigh != null)
			{
				Transform firstCommonAncestor = Hierarchy.GetFirstCommonAncestor(references.leftUpperArm, references.rightUpperArm);
				if (firstCommonAncestor != null)
				{
					Transform[] array = new Transform[]
					{
						firstCommonAncestor
					};
					Hierarchy.AddAncestors(array[0], references.pelvis, ref array);
					references.spine = new Transform[0];
					for (int i = array.Length - 1; i > -1; i--)
					{
						if (BipedReferences.AddBoneToSpine(array[i], ref references, autoDetectParams))
						{
							Array.Resize<Transform>(ref references.spine, references.spine.Length + 1);
							references.spine[references.spine.Length - 1] = array[i];
						}
					}
					if (references.head == null)
					{
						for (int j = 0; j < firstCommonAncestor.childCount; j++)
						{
							Transform child = firstCommonAncestor.GetChild(j);
							if (!Hierarchy.ContainsChild(child, references.leftUpperArm) && !Hierarchy.ContainsChild(child, references.rightUpperArm))
							{
								references.head = child;
								break;
							}
						}
					}
				}
			}
			Transform[] bonesOfType = BipedNaming.GetBonesOfType(BipedNaming.BoneType.Eye, componentsInChildren);
			references.eyes = new Transform[0];
			if (autoDetectParams.includeEyes)
			{
				for (int k = 0; k < bonesOfType.Length; k++)
				{
					if (BipedReferences.AddBoneToEyes(bonesOfType[k], ref references, autoDetectParams))
					{
						Array.Resize<Transform>(ref references.eyes, references.eyes.Length + 1);
						references.eyes[references.eyes.Length - 1] = bonesOfType[k];
					}
				}
			}
		}

		// Token: 0x060006C0 RID: 1728 RVA: 0x0003C608 File Offset: 0x0003A808
		public static void AssignHumanoidReferences(ref BipedReferences references, Animator animator, BipedReferences.AutoDetectParams autoDetectParams)
		{
			if (references == null)
			{
				references = new BipedReferences();
			}
			if (animator == null || !animator.isHuman)
			{
				return;
			}
			references.spine = new Transform[0];
			references.eyes = new Transform[0];
			references.head = animator.GetBoneTransform(HumanBodyBones.Head);
			references.leftThigh = animator.GetBoneTransform(HumanBodyBones.LeftUpperLeg);
			references.leftCalf = animator.GetBoneTransform(HumanBodyBones.LeftLowerLeg);
			references.leftFoot = animator.GetBoneTransform(HumanBodyBones.LeftFoot);
			references.rightThigh = animator.GetBoneTransform(HumanBodyBones.RightUpperLeg);
			references.rightCalf = animator.GetBoneTransform(HumanBodyBones.RightLowerLeg);
			references.rightFoot = animator.GetBoneTransform(HumanBodyBones.RightFoot);
			references.leftUpperArm = animator.GetBoneTransform(HumanBodyBones.LeftUpperArm);
			references.leftForearm = animator.GetBoneTransform(HumanBodyBones.LeftLowerArm);
			references.leftHand = animator.GetBoneTransform(HumanBodyBones.LeftHand);
			references.rightUpperArm = animator.GetBoneTransform(HumanBodyBones.RightUpperArm);
			references.rightForearm = animator.GetBoneTransform(HumanBodyBones.RightLowerArm);
			references.rightHand = animator.GetBoneTransform(HumanBodyBones.RightHand);
			references.pelvis = animator.GetBoneTransform(HumanBodyBones.Hips);
			BipedReferences.AddBoneToHierarchy(ref references.spine, animator.GetBoneTransform(HumanBodyBones.Spine));
			BipedReferences.AddBoneToHierarchy(ref references.spine, animator.GetBoneTransform(HumanBodyBones.Chest));
			if (references.leftUpperArm != null && !BipedReferences.IsNeckBone(animator.GetBoneTransform(HumanBodyBones.Neck), references.leftUpperArm))
			{
				BipedReferences.AddBoneToHierarchy(ref references.spine, animator.GetBoneTransform(HumanBodyBones.Neck));
			}
			if (autoDetectParams.includeEyes)
			{
				BipedReferences.AddBoneToHierarchy(ref references.eyes, animator.GetBoneTransform(HumanBodyBones.LeftEye));
				BipedReferences.AddBoneToHierarchy(ref references.eyes, animator.GetBoneTransform(HumanBodyBones.RightEye));
			}
		}

		// Token: 0x060006C1 RID: 1729 RVA: 0x0003C7BC File Offset: 0x0003A9BC
		public static bool SetupError(BipedReferences references, ref string errorMessage)
		{
			if (!references.isFilled)
			{
				errorMessage = "BipedReferences contains one or more missing Transforms.";
				return true;
			}
			return BipedReferences.LimbError(references.leftThigh, references.leftCalf, references.leftFoot, ref errorMessage) || BipedReferences.LimbError(references.rightThigh, references.rightCalf, references.rightFoot, ref errorMessage) || BipedReferences.LimbError(references.leftUpperArm, references.leftForearm, references.leftHand, ref errorMessage) || BipedReferences.LimbError(references.rightUpperArm, references.rightForearm, references.rightHand, ref errorMessage) || BipedReferences.SpineError(references, ref errorMessage) || BipedReferences.EyesError(references, ref errorMessage);
		}

		// Token: 0x060006C2 RID: 1730 RVA: 0x0003C878 File Offset: 0x0003AA78
		public static bool SetupWarning(BipedReferences references, ref string warningMessage)
		{
			return BipedReferences.LimbWarning(references.leftThigh, references.leftCalf, references.leftFoot, ref warningMessage) || BipedReferences.LimbWarning(references.rightThigh, references.rightCalf, references.rightFoot, ref warningMessage) || BipedReferences.LimbWarning(references.leftUpperArm, references.leftForearm, references.leftHand, ref warningMessage) || BipedReferences.LimbWarning(references.rightUpperArm, references.rightForearm, references.rightHand, ref warningMessage) || BipedReferences.SpineWarning(references, ref warningMessage) || BipedReferences.EyesWarning(references, ref warningMessage) || BipedReferences.RootHeightWarning(references, ref warningMessage) || BipedReferences.FacingAxisWarning(references, ref warningMessage);
		}

		// Token: 0x060006C3 RID: 1731 RVA: 0x00006621 File Offset: 0x00004821
		public static bool IsNeckBone(Transform bone, Transform leftUpperArm)
		{
			return (!(leftUpperArm.parent != null) || !(leftUpperArm.parent == bone)) && !Hierarchy.IsAncestor(leftUpperArm, bone);
		}

		// Token: 0x060006C4 RID: 1732 RVA: 0x00006656 File Offset: 0x00004856
		public static bool AddBoneToEyes(Transform bone, ref BipedReferences references, BipedReferences.AutoDetectParams autoDetectParams)
		{
			return (!(references.head != null) || Hierarchy.IsAncestor(bone, references.head)) && !(bone.GetComponent<SkinnedMeshRenderer>() != null);
		}

		// Token: 0x060006C5 RID: 1733 RVA: 0x0003C93C File Offset: 0x0003AB3C
		public static bool AddBoneToSpine(Transform bone, ref BipedReferences references, BipedReferences.AutoDetectParams autoDetectParams)
		{
			if (bone == references.root)
			{
				return false;
			}
			bool flag = bone == references.leftThigh.parent;
			if (flag && !autoDetectParams.legsParentInSpine)
			{
				return false;
			}
			if (references.pelvis != null)
			{
				if (bone == references.pelvis)
				{
					return false;
				}
				if (Hierarchy.IsAncestor(references.pelvis, bone))
				{
					return false;
				}
			}
			return true;
		}

		// Token: 0x060006C6 RID: 1734 RVA: 0x0003C9C0 File Offset: 0x0003ABC0
		public static void DetectLimb(BipedNaming.BoneType boneType, BipedNaming.BoneSide boneSide, ref Transform firstBone, ref Transform secondBone, ref Transform lastBone, Transform[] transforms)
		{
			Transform[] bonesOfTypeAndSide = BipedNaming.GetBonesOfTypeAndSide(boneType, boneSide, transforms);
			if (bonesOfTypeAndSide.Length < 3)
			{
				return;
			}
			if (bonesOfTypeAndSide.Length == 3)
			{
				firstBone = bonesOfTypeAndSide[0];
				secondBone = bonesOfTypeAndSide[1];
				lastBone = bonesOfTypeAndSide[2];
			}
			if (bonesOfTypeAndSide.Length > 3)
			{
				firstBone = bonesOfTypeAndSide[0];
				secondBone = bonesOfTypeAndSide[2];
				lastBone = bonesOfTypeAndSide[bonesOfTypeAndSide.Length - 1];
			}
		}

		// Token: 0x060006C7 RID: 1735 RVA: 0x00006692 File Offset: 0x00004892
		public static void AddBoneToHierarchy(ref Transform[] bones, Transform transform)
		{
			if (transform == null)
			{
				return;
			}
			Array.Resize<Transform>(ref bones, bones.Length + 1);
			bones[bones.Length - 1] = transform;
		}

		// Token: 0x060006C8 RID: 1736 RVA: 0x0003CA18 File Offset: 0x0003AC18
		public static bool LimbError(Transform bone1, Transform bone2, Transform bone3, ref string errorMessage)
		{
			if (bone1 == null)
			{
				errorMessage = "Bone 1 of a BipedReferences limb is null.";
				return true;
			}
			if (bone2 == null)
			{
				errorMessage = "Bone 2 of a BipedReferences limb is null.";
				return true;
			}
			if (bone3 == null)
			{
				errorMessage = "Bone 3 of a BipedReferences limb is null.";
				return true;
			}
			Transform transform = (Transform)Hierarchy.ContainsDuplicate(new Transform[]
			{
				bone1,
				bone2,
				bone3
			});
			if (transform != null)
			{
				errorMessage = transform.name + " is represented multiple times in the same BipedReferences limb.";
				return true;
			}
			if (bone2.position == bone1.position)
			{
				errorMessage = "Second bone's position equals first bone's position in the biped's limb.";
				return true;
			}
			if (bone3.position == bone2.position)
			{
				errorMessage = "Third bone's position equals second bone's position in the biped's limb.";
				return true;
			}
			if (!Hierarchy.HierarchyIsValid(new Transform[]
			{
				bone1,
				bone2,
				bone3
			}))
			{
				errorMessage = string.Concat(new string[]
				{
					"BipedReferences limb hierarchy is invalid. Bone transforms in a limb do not belong to the same ancestry. Please make sure the bones are parented to each other. Bones: ",
					bone1.name,
					", ",
					bone2.name,
					", ",
					bone3.name
				});
				return true;
			}
			return false;
		}

		// Token: 0x060006C9 RID: 1737 RVA: 0x0003CB40 File Offset: 0x0003AD40
		public static bool LimbWarning(Transform bone1, Transform bone2, Transform bone3, ref string warningMessage)
		{
			Vector3 lhs = Vector3.Cross(bone2.position - bone1.position, bone3.position - bone1.position);
			if (lhs == Vector3.zero)
			{
				warningMessage = string.Concat(new string[]
				{
					"BipedReferences limb is completely stretched out in the initial pose. IK solver can not calculate the default bend plane for the limb. Please make sure you character's limbs are at least slightly bent in the initial pose. First bone: ",
					bone1.name,
					", second bone: ",
					bone2.name,
					"."
				});
				return true;
			}
			return false;
		}

		// Token: 0x060006CA RID: 1738 RVA: 0x0003CBC0 File Offset: 0x0003ADC0
		public static bool SpineError(BipedReferences references, ref string errorMessage)
		{
			if (references.spine.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < references.spine.Length; i++)
			{
				if (references.spine[i] == null)
				{
					errorMessage = "BipedReferences spine bone at index " + i + " is null.";
					return true;
				}
			}
			Transform transform = (Transform)Hierarchy.ContainsDuplicate(references.spine);
			if (transform != null)
			{
				errorMessage = transform.name + " is represented multiple times in BipedReferences spine.";
				return true;
			}
			if (!Hierarchy.HierarchyIsValid(references.spine))
			{
				errorMessage = "BipedReferences spine hierarchy is invalid. Bone transforms in the spine do not belong to the same ancestry. Please make sure the bones are parented to each other.";
				return true;
			}
			for (int j = 0; j < references.spine.Length; j++)
			{
				bool flag = false;
				if (j == 0 && references.spine[j].position == references.pelvis.position)
				{
					flag = true;
				}
				if (j != 0 && references.spine.Length > 1 && references.spine[j].position == references.spine[j - 1].position)
				{
					flag = true;
				}
				if (flag)
				{
					errorMessage = "Biped's spine bone nr " + j + " position is the same as it's parent spine/pelvis bone's position. Please remove this bone from the spine.";
					return true;
				}
			}
			return false;
		}

		// Token: 0x060006CB RID: 1739 RVA: 0x00004133 File Offset: 0x00002333
		public static bool SpineWarning(BipedReferences references, ref string warningMessage)
		{
			return false;
		}

		// Token: 0x060006CC RID: 1740 RVA: 0x0003CD0C File Offset: 0x0003AF0C
		public static bool EyesError(BipedReferences references, ref string errorMessage)
		{
			if (references.eyes.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < references.eyes.Length; i++)
			{
				if (references.eyes[i] == null)
				{
					errorMessage = "BipedReferences eye bone at index " + i + " is null.";
					return true;
				}
			}
			Transform transform = (Transform)Hierarchy.ContainsDuplicate(references.eyes);
			if (transform != null)
			{
				errorMessage = transform.name + " is represented multiple times in BipedReferences eyes.";
				return true;
			}
			return false;
		}

		// Token: 0x060006CD RID: 1741 RVA: 0x00004133 File Offset: 0x00002333
		public static bool EyesWarning(BipedReferences references, ref string warningMessage)
		{
			return false;
		}

		// Token: 0x060006CE RID: 1742 RVA: 0x0003CDA0 File Offset: 0x0003AFA0
		public static bool RootHeightWarning(BipedReferences references, ref string warningMessage)
		{
			if (references.head == null)
			{
				return false;
			}
			float verticalOffset = BipedReferences.GetVerticalOffset(references.head.position, references.leftFoot.position, references.root.rotation);
			float verticalOffset2 = BipedReferences.GetVerticalOffset(references.root.position, references.leftFoot.position, references.root.rotation);
			if (verticalOffset2 / verticalOffset > 0.2f)
			{
				warningMessage = "Biped's root Transform's position should be at ground level relative to the character (at the character's feet not at it's pelvis).";
				return true;
			}
			return false;
		}

		// Token: 0x060006CF RID: 1743 RVA: 0x0003CE28 File Offset: 0x0003B028
		public static bool FacingAxisWarning(BipedReferences references, ref string warningMessage)
		{
			Vector3 vector = references.rightHand.position - references.leftHand.position;
			Vector3 vector2 = references.rightFoot.position - references.leftFoot.position;
			float num = Vector3.Dot(vector.normalized, references.root.right);
			float num2 = Vector3.Dot(vector2.normalized, references.root.right);
			if (num < 0f || num2 < 0f)
			{
				warningMessage = "Biped does not seem to be facing it's forward axis. Please make sure that in the initial pose the character is facing towards the positive Z axis of the Biped root gameobject.";
				return true;
			}
			return false;
		}

		// Token: 0x060006D0 RID: 1744 RVA: 0x0003CEC0 File Offset: 0x0003B0C0
		public static float GetVerticalOffset(Vector3 p1, Vector3 p2, Quaternion rotation)
		{
			return (Quaternion.Inverse(rotation) * (p1 - p2)).y;
		}

		// Token: 0x04000643 RID: 1603
		public Transform root;

		// Token: 0x04000644 RID: 1604
		public Transform pelvis;

		// Token: 0x04000645 RID: 1605
		public Transform leftThigh;

		// Token: 0x04000646 RID: 1606
		public Transform leftCalf;

		// Token: 0x04000647 RID: 1607
		public Transform leftFoot;

		// Token: 0x04000648 RID: 1608
		public Transform rightThigh;

		// Token: 0x04000649 RID: 1609
		public Transform rightCalf;

		// Token: 0x0400064A RID: 1610
		public Transform rightFoot;

		// Token: 0x0400064B RID: 1611
		public Transform leftUpperArm;

		// Token: 0x0400064C RID: 1612
		public Transform leftForearm;

		// Token: 0x0400064D RID: 1613
		public Transform leftHand;

		// Token: 0x0400064E RID: 1614
		public Transform rightUpperArm;

		// Token: 0x0400064F RID: 1615
		public Transform rightForearm;

		// Token: 0x04000650 RID: 1616
		public Transform rightHand;

		// Token: 0x04000651 RID: 1617
		public Transform head;

		// Token: 0x04000652 RID: 1618
		public Transform[] spine = new Transform[0];

		// Token: 0x04000653 RID: 1619
		public Transform[] eyes = new Transform[0];

		// Token: 0x020000F0 RID: 240
		public struct AutoDetectParams
		{
			// Token: 0x060006D1 RID: 1745 RVA: 0x000066B7 File Offset: 0x000048B7
			public AutoDetectParams(bool legsParentInSpine, bool includeEyes)
			{
				this.legsParentInSpine = legsParentInSpine;
				this.includeEyes = includeEyes;
			}

			// Token: 0x1700009F RID: 159
			// (get) Token: 0x060006D2 RID: 1746 RVA: 0x000066C7 File Offset: 0x000048C7
			public static BipedReferences.AutoDetectParams Default
			{
				get
				{
					return new BipedReferences.AutoDetectParams(true, true);
				}
			}

			// Token: 0x04000654 RID: 1620
			public bool legsParentInSpine;

			// Token: 0x04000655 RID: 1621
			public bool includeEyes;
		}
	}
}
